package com.school.information.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.school.information.core.constant.CommonConstant;
import com.school.information.core.exception.ServiceException;
import com.school.information.core.service.CustomPasswordService;
import com.school.information.dto.UserDTO;
import com.school.information.entity.SysUserEntity;
import com.school.information.entity.SysUserRoleEntity;
import com.school.information.enums.result.SysResultEnum;
import com.school.information.enums.status.EnabledEnum;
import com.school.information.mapper.SysUserMapper;
import com.school.information.qo.SysUserQO;
import com.school.information.service.SysUserRoleService;
import com.school.information.service.SysUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService {
    @Resource
    private CustomPasswordService customPasswordService;
    @Resource
    private SysUserRoleService userRoleService;


    @Override
    public IPage<SysUserEntity> pageList(SysUserQO sysUser) {
        LambdaQueryWrapper<SysUserEntity> queryWrapper = Wrappers.<SysUserEntity>query().lambda().orderByDesc(SysUserEntity::getCreateTime);
        // 去除超级管理员账号
        queryWrapper.ne(SysUserEntity::getId, CommonConstant.ADMIN_USER_ID);
        if (StringUtils.isNotBlank(sysUser.getPhone())) {
            queryWrapper.like(SysUserEntity::getPhone, sysUser.getPhone());
        }
        if (StringUtils.isNotBlank(sysUser.getRealName())) {
            queryWrapper.like(SysUserEntity::getRealName, sysUser.getRealName());
        }
        return this.page(new Page<>(sysUser.getCurrent(), sysUser.getSize()), queryWrapper);
    }

    /**
     * 根据手机号查询用户信息
     *
     * @param phone
     * @return
     */
    @Override
    public SysUserEntity getByPhone(String phone) {
        return this.getOne(Wrappers.<SysUserEntity>lambdaQuery().eq(SysUserEntity::getPhone, phone));
    }

    /**
     * 新增用户信息
     *
     * @param userDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveInfo(UserDTO userDTO) {
        boolean result = false;
        SysUserEntity sysUser = userDTO.getSysUser();
        SysUserEntity userPhone = getByPhone(sysUser.getPhone());
        log.info("##userPhone={}", userPhone);
        if (Objects.nonNull(userPhone) && StringUtils.isNotBlank(userPhone.getPhone())) {
            log.error("##员工手机号已存在");
            throw new ServiceException(SysResultEnum.USER_PHONE_EXISTED);
        }
        try {
            sysUser.setIsEnabled(EnabledEnum.ENABLE).setPassword(customPasswordService.generatePassword(CommonConstant.DEFAULT_PASSWORD));
            result = this.save(sysUser);
            if (result) {
                // 插入用户和角色关系
                insertUserRole(sysUser.getId(), userDTO.getRoleIds());
            }
        } catch (DuplicateKeyException e) {
            log.error("##唯一索引异常，用户信息已存在;" + e.getMessage());
            throw new ServiceException(SysResultEnum.UK_INDEX_EXCEPTION);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateInfo(UserDTO userDTO) {
        boolean result = false;
        SysUserEntity sysUser = userDTO.getSysUser();
        SysUserEntity userPhone = getByPhone(sysUser.getPhone());
        SysUserEntity oldUser = getById(sysUser.getId());
        log.info("##oldUser={}", oldUser);
        if (Objects.nonNull(userPhone) && StringUtils.isNotBlank(userPhone.getPhone())
                && !userPhone.getPhone().equals(oldUser.getPhone())) {
            log.error("##员工手机号已存在");
            throw new ServiceException(SysResultEnum.USER_PHONE_EXISTED);
        }
        oldUser.setRealName(sysUser.getRealName()).setGender(sysUser.getGender())
                .setPhone(sysUser.getPhone()).setEmail(sysUser.getEmail()).setRemark(sysUser.getRemark());
        result = this.updateById(oldUser);
        if (result) {
            // 插入用户和角色关系
            insertUserRole(sysUser.getId(), userDTO.getRoleIds());
        }
        return result;
    }

    @Override
    public boolean updateStatus(Long id, EnabledEnum enable) {
        SysUserEntity oldUser = getById(id);
        oldUser.setIsEnabled(enable);
        return updateById(oldUser);
    }

    @Override
    public boolean resetPwd(Long id) {
        SysUserEntity oldUser = getById(id);
        oldUser.setPassword(customPasswordService.generatePassword(CommonConstant.DEFAULT_PASSWORD));
        return updateById(oldUser);
    }

    @Override
    public Map<Long, SysUserEntity> getUserMap(List<Long> userIds) {
        Map<Long, SysUserEntity> resultMap = new HashMap<>();
        List<SysUserEntity> userList = this.listByIds(userIds);
        userList.forEach(sysUser -> {
            resultMap.put(sysUser.getId(), sysUser);
        });
        return resultMap;
    }

    /**
     * 插入用户和角色的关系
     *
     * @param userId
     */
    private void insertUserRole(Long userId, List<Long> roleIdList) {
        // 先根据用户，删除该用户下所有的角色信息
        userRoleService.delByUserId(userId);
        List<SysUserRoleEntity> list = new LinkedList<>();
        // 插入用户和角色关系信息
        roleIdList.forEach(item -> {
            SysUserRoleEntity userRole = new SysUserRoleEntity();
            userRole.setUserId(userId).setRoleId(item);
            list.add(userRole);
        });
        if (!CollectionUtils.isEmpty(list)) {
            userRoleService.saveBatch(list);
        }
    }
}
